﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Algorytm;
using ScheduleMaker.ConfigManager;
using ScheduleMaker.DB;
using ScheduleMaker.DB.Domain;
using ScheduleMaker.DB.Domain.Core;
using ScheduleMaker.DB.CoreDAO;

namespace ScheduleMaker.Converter
{
    public class DomainConverter
    {
        private static ClassHourDAO classHourDAO;
        private static DayDAO dayDAO;
        private static ClassroomDAO classroomDAO;
        private static TeacherDAO teacherDAO;
        private static SubjectDAO subjectDAO;
        private static GroupDAO groupDAO;

        private static IList<ClassHour> classHours;

        static DomainConverter()
        {
            Config config = new Config();
            config.Type = Mode.School;

            if (ConfigManager.ConfigManager.isConfigLoaded())
            {
                config = ConfigManager.ConfigManager.getConfiguration();
                classHourDAO = DAOFactory.getClassHourDAO(config.Type);
                dayDAO = DAOFactory.getDayDAO(config.Type);
                classroomDAO = DAOFactory.getClassroomDAO(config.Type);
                teacherDAO = DAOFactory.getTeacherDAO(config.Type);
                subjectDAO = DAOFactory.getSubjectDAO(config.Type);
                groupDAO = DAOFactory.getGroupDAO(config.Type);

                classHours = classHourDAO.getAll();
                classHours.OrderBy(x => x.Begin);
            }
        }

        private static int getIndex<T>(T obj, IList<T> objects)
        {
            int index = -1;
            for (int i = 0; i < objects.Count; i++)
            {
                if (objects[i].Equals(obj))
                {
                    index = i;
                    break;
                }
            }

            return index;
        }

        public static Day getDay(DayOfWeek dayOfWeek)
        {
            Day day = null;

            switch (dayOfWeek)
            {
                case DayOfWeek.Monday:
                    day = dayDAO.getById(1);
                    break;
                case DayOfWeek.Tuesday:
                    day = dayDAO.getById(2);
                    break;
                case DayOfWeek.Wednesday:
                    day = dayDAO.getById(3);
                    break;
                case DayOfWeek.Thursday:
                    day = dayDAO.getById(4);
                    break;
                case DayOfWeek.Friday:
                    day = dayDAO.getById(5);
                    break;
                case DayOfWeek.Saturday:
                    day = dayDAO.getById(6);
                    break;
                case DayOfWeek.Sunday:
                    day = dayDAO.getById(7);
                    break;
            }

            return day;
        }

        public static DayOfWeek getDayOfWeek(Day day)
        {
            DayOfWeek dayOfWeek = DayOfWeek.Monday;
            switch (day.Id)
            {
                case 1:
                    dayOfWeek = DayOfWeek.Monday;
                    break;
                case 2:
                    dayOfWeek = DayOfWeek.Tuesday;
                    break;
                case 3:
                    dayOfWeek = DayOfWeek.Wednesday;
                    break;
                case 4:
                    dayOfWeek = DayOfWeek.Thursday;
                    break;
                case 5:
                    dayOfWeek = DayOfWeek.Friday;
                    break;
                case 6:
                    dayOfWeek = DayOfWeek.Saturday;
                    break;
                case 7:
                    dayOfWeek = DayOfWeek.Sunday;
                    break;
            }

            return dayOfWeek;
        }

        public static Algorytm_Przedzial getAlgorytm_Przedzial(ClassHour classHour, Day day)
        {
            int index = getIndex<ClassHour>(classHour, classHours);
            return new Algorytm_Przedzial(day.Id, index, index + 1);
        }

        public static IList<Algorytm_Przedzial> getAlgorytm_Przedzial(Hour hour)
        {
            IList<ClassHour> classHours = classHourDAO.getClassHoursFromInterval(hour);
            IList<Algorytm_Przedzial> przedzialy = new List<Algorytm_Przedzial>();

            foreach (var classHour in classHours)
            {
                przedzialy.Add(getAlgorytm_Przedzial(classHour, hour.Day));
            }

            return przedzialy;
        }

        public static Algorytm_Przedzial getAlgorytm_Przedzial2(Hour hour)
        {
            IList<ClassHour> classHours = classHourDAO.getClassHoursFromInterval(hour);
            ClassHour first = classHours.First<ClassHour>();
            ClassHour last = classHours.Last<ClassHour>();
            int indexFirst = getIndex<ClassHour>(first, classHours);
            int indexLast = getIndex<ClassHour>(last, classHours);

            return new Algorytm_Przedzial(hour.Day.Id, indexFirst, indexLast);
        }

        public static IList<Algorytm_Przedzial> getAlgorytm_Przedzial2(IList<Hour> hours)
        {
            IList<Algorytm_Przedzial> przedzialy = new List<Algorytm_Przedzial>();
            foreach (var hour in hours)
            {
                przedzialy.Add(getAlgorytm_Przedzial2(hour));
            }

            return przedzialy;
        }

        public static Algorytm_Zajecia getAlgorytm_Zajecia(Subject subject)
        {
            int hours = 0;
            foreach (var group in subject.Groups)
            {
                hours = +group.SubjectsCount[subject];
            }

            //return new Algorytm_Zajecia(subject.Id, hours, subject.Groups.Count); 
            return new Algorytm_Zajecia(subject.Id, hours, 1);

        }

        public static IList<Algorytm_Zajecia> getAlgorytm_Zajecia(IList<Subject> subjects)
        {
            IList<Algorytm_Zajecia> zajecia = new List<Algorytm_Zajecia>();
            foreach (var subject in subjects)
            {
                zajecia.Add(getAlgorytm_Zajecia(subject));
            }
            return zajecia;
        }

        public static Schedule getSchedule(Algorytm_Element_Planu elementPlanu)
        {
            Schedule schedule = null;
            if (ConfigManager.ConfigManager.isConfigLoaded())
            {
                Config config = ConfigManager.ConfigManager.getConfiguration();
                if (config.Type == Mode.School)
                {
                    schedule = new ScheduleSchool();
                }
                else
                {
                    schedule = new ScheduleUniversity();
                }
                schedule.ClassHour = classHourDAO.getById(elementPlanu.godzina + 1);
                schedule.Day = dayDAO.getById(elementPlanu.dzien);
                schedule.Classroom = classroomDAO.getById(elementPlanu.sala);
                schedule.Teacher = teacherDAO.getById(elementPlanu.nauczyciel);
                schedule.Subject = subjectDAO.getById(elementPlanu.przedmiot);
                if (config.Type == Mode.School)
                {
                    schedule.Group = groupDAO.getById(elementPlanu.klasa);
                }
            }

            return schedule;
        }

        public static Schedule getSchedule(Algorytm_Element_wyniku elementWyniku)
        {
            Schedule schedule = null;
            if (ConfigManager.ConfigManager.isConfigLoaded())
            {
                Config config = ConfigManager.ConfigManager.getConfiguration();
                if (config.Type == Mode.School)
                {
                    schedule = new ScheduleSchool();
                }
                else
                {
                    schedule = new ScheduleUniversity();
                }
                schedule.ClassHour = classHourDAO.getById(elementWyniku.Godzina + 1);
                schedule.Day = dayDAO.getById(elementWyniku.Dzien);
                schedule.Classroom = classroomDAO.getById(elementWyniku.Sala);
                schedule.Teacher = teacherDAO.getById(elementWyniku.Nauczyciel);
                schedule.Subject = subjectDAO.getById(elementWyniku.Przedmiot);
                if (config.Type == Mode.School)
                {
                    schedule.Group = groupDAO.getById(elementWyniku.Klasa);
                }
            }

            return schedule;
        }

        public static IList<Schedule> getSchedule(IList<Algorytm_Element_wyniku> elements)
        {
            IList<Schedule> scheduleRecords = new List<Schedule>();
            foreach (var element in elements)
            {
                scheduleRecords.Add(getSchedule(element));
            }

            return scheduleRecords;
        }

        public static EmergencySchedule getEmergencySchedule(Algorytm_Element_wyniku elementWyniku, DateTime date_p)
        {
            EmergencySchedule emergencySchedule = null;
            if (ConfigManager.ConfigManager.isConfigLoaded())
            {
                Config config = ConfigManager.ConfigManager.getConfiguration();
                if (config.Type == Mode.School)
                {
                    emergencySchedule = new EmergencyScheduleSchool();
                }
                else
                {
                    emergencySchedule = new EmergencyScheduleUniversity();
                }
                emergencySchedule.ClassHour = classHourDAO.getById(elementWyniku.Godzina + 1);
                emergencySchedule.Day = dayDAO.getById(elementWyniku.Dzien);
                emergencySchedule.Classroom = classroomDAO.getById(elementWyniku.Sala);
                emergencySchedule.Teacher = teacherDAO.getById(elementWyniku.Nauczyciel);
                emergencySchedule.Subject = subjectDAO.getById(elementWyniku.Przedmiot);
                if (config.Type == Mode.School)
                {
                    emergencySchedule.Group = groupDAO.getById(elementWyniku.Klasa);
                }
                emergencySchedule.Divided = elementWyniku.Czy_zajecia_sa_grupowe;
                emergencySchedule.Date = (date_p.Date).Ticks;
                System.Console.WriteLine("================");
                System.Console.WriteLine(emergencySchedule.Date.ToString());
                System.Console.WriteLine("================");
                
               
            }

            return emergencySchedule;
        }
        public static IList<EmergencySchedule> getEmergencySchedule(IList<Algorytm_Element_wyniku> elements, DateTime date)
        {
            IList<EmergencySchedule> emergencyScheduleRecords = new List<EmergencySchedule>();
            foreach (var element in elements)
            {
                emergencyScheduleRecords.Add(getEmergencySchedule(element, date));
            }

            return emergencyScheduleRecords;
        }
        //
        public static Algorytm_Element_wyniku getAlgorytm_Element_wyniku(Schedule schedule)
        {
            
            Algorytm_Element_wyniku algorytm_element_wyniku = null;
            if (ConfigManager.ConfigManager.isConfigLoaded())
            {
                Config config = ConfigManager.ConfigManager.getConfiguration();
                if (config.Type == Mode.School)
                {
                    int klasa = schedule.Group.Id;
                    int nauczyciel = schedule.Teacher.Id;
                    int przedmiot = schedule.Subject.Id;
                    int sala = schedule.Classroom.Id;
                    int dzien = schedule.Day.Id;
                    int godzina = schedule.ClassHour.Id-1;
                    int dlugosc = 1;
                    bool czy_zajecia_grupowe = false ;
                    algorytm_element_wyniku = new Algorytm_Element_wyniku(klasa,nauczyciel,przedmiot,sala,dzien,godzina,dlugosc,czy_zajecia_grupowe);
                }
                else if (config.Type == Mode.University)
                {
                    //TODO: jak jest uzupelniana klasa, -1 ?
                    int klasa = schedule.Group.Id;
                    int nauczyciel = schedule.Teacher.Id;
                    int przedmiot = schedule.Subject.Id;
                    int sala = schedule.Classroom.Id;
                    int dzien = schedule.Day.Id;
                    int godzina = schedule.ClassHour.Id;
                    int dlugosc = schedule.Subject.Time;
                    bool czy_zajecia_grupowe = false;
                    algorytm_element_wyniku = new Algorytm_Element_wyniku(klasa, nauczyciel, przedmiot, sala, dzien, godzina, dlugosc, czy_zajecia_grupowe);
                }
            }

            return algorytm_element_wyniku;
        }

        public static List<Algorytm_Element_wyniku> getAlgorytmElementWyniku(IList<Schedule> elements)
        {
            List<Algorytm_Element_wyniku> algorytm_element_wyniku = new List<Algorytm_Element_wyniku>();
            foreach (var element in elements)
            {
                algorytm_element_wyniku.Add(getAlgorytm_Element_wyniku(element));
            }

            return algorytm_element_wyniku;
        }
        //
    }
}